Intégration de Mathematica dans la pédagogie des grandes écoles

Rémi Barrère (rbarrere@ensmm.fr)

Ecole Nationale Supérieure de 
Mécanique et des Microtechniques
(Université de Franche-Comté)
Besançon, France

Résumé

Grâce à son langage unificateur à syntaxe mathématique, Mathematica intéresse aussi bien les mathématiciens que les informaticiens ou les physiciens (en fait toutes les spécialités scientifiques). En établissant des correspondances entre les domaines de la logique, du calcul et des techniques de programmation, il stimule le dialogue interdisciplinaire autour de l'activité pivot qu'est la modélisation. Après avoir explicité ces idées, nous en décrirons une application pédagogique sous forme de mini-projets pour élèves-ingénieurs puis nous indiquerons quelques perspectives pour les applications professionnelles en recherche ou dans le domaine de l'ingénierie.

Introduction

Nous avons assisté ces dernières décennies à un changement radical des façons de faire en calcul scientifique, que l'on pourrait présenter comme transition de la règle à calcul et des tables numériques vers l'ordinateur et les logiciels de manipulations symboliques. La dernière douzaine d'années en particulier a consacré la vulgarisation du calcul formel et de la programmation symbolique.

Loin de mettre les scientifiques au repos forcé comme on a pu le prétendre, ces outils contemporains exigent des compétences rénovées et multidisciplinaires à la frontière des mathématiques, de la physique et de l'informatique. Ils offrent en retour des possibilités nouvelles que les langages procéduraux et les techniques numériques ne permettent pas. Cet exposé décrit comment le tournant a été pris dans une école d'ingénieurs du groupe des ENSI.

J'insisterai d'abord sur le pouvoir unificateur de Mathematica qui le rend attrayant aussi bien pour les mathématiciens que les physiciens ou les informaticiens et contribue même à les réunir autour de l'activité pivot qu'est la modélisation. Je décrirai alors une application pédagogique consistant en des mini-projets pour élèves-ingénieurs, puis je mentionnerai quelques perspectives pour les applications professionnelles en recherche ou dans le domaine de l'ingénierie.

Un langage unificateur pour les mathématiques, la physique et l'informatique

Bien plus qu'un simple système de calcul formel (comme on le laisse trop souvent entendre), Mathematica rassemble au sein d'une interface programmable un système de calcul formel, une bibliothèque numérique et graphique ainsi qu'un langage multiparadigme dont la syntaxe mime celle des mathématiques.

Ce langage symbolique se prête particulièrement bien à la formulation des problèmes scientifiques. Foncièrement, en Mathematica, les programmes sont des collections de fonctions (de définitions algorithmiques de fonctions en fait), exprimées à peu près comme des formules mathématiques. A ce titre, ils intéressent :

- les physiciens (ainsi que chimistes, biologistes, économistes…) en tant que règles de calcul pour la simulation des systèmes ou des processus.

Une fois établies les règles de calcul relatives à un domaine, celles-ci sont traduites en programmes qui s'expriment quasiment comme des formules mathématiques ; ainsi, on passe directement de la modélisation à la programmation puis à la simulation (par calcul numérique ou symbolique) et à la visualisation (à l'aide des commandes graphiques).

- les mathématiciens en tant que systèmes d'axiomes pouvant être étudiés dans le cadre de la théorie des modèles (sémantique dénotationnelle).

Les programmes s'exprimant comme des définitions de fonctions (des règles de transformation en fait) sont traités comme axiomes d'une axiomatique égalitaire dans le cadre de la théorie des modèles ; la syntaxe de Mathematica facilite également les preuves de programmes (sémantique « pré-post » et correspondance de Curry-Howard) et les analyses de complexité.

- les informaticiens en tant que fonctions ou procédures opérant sur des structures de données et qui mettent en jeu des techniques fondamentales telles que le typage, le polymorphisme, la récursivité, voire les objets logiciels.

Les programmes ainsi construits mettent en œuvre des techniques développées en informatique : les expressions fonctionnelles sont intérieurement des listes chaînées ; les têtes de ces expressions désignent des types (typage faible) ; on peut définir des fonctions polymorphes, recourir à la récursivité ; on crée de petites bases de données sous forme de fonctions définies par cas ; la forme des expressions est identifiée par un algorithme de filtrage ; certains aspects de la programmation orientée objets sont présents (classes, méthodes)…

Un langage unificateur

Impedance[Resistor[r_], w_:  ω] ^:= r
Impedance[Inductor[l_], w_:  ω] ^:= I l w
Impedance[Capacitor[c_], 
        w_:  ω] ^:= -I/(c w)

\(Impedance[SeriesMount[s_], w_:  ω] ^:= 
	
      Apply[Plus, Thread[Impedance[s, w]]]\)
\(Impedance[ParallelMount[s_], w_:  ω] ^:= 
	
      1/Apply[Plus, 1/Thread[Impedance[s, w]]]\)

Impedance[
        SeriesMount[{Resistor[
              r], 
ParallelMount[{Capacitor[c], 
                Inductor[l]}]
}]
] // 
      Simplify

Dans cet exemple dédié au calcul d'impédances, on a trois règles pour définir les impédances des composants élémentaires et deux autres pour les assemblages série et parallèle. Celles-ci peuvent être vues :

- comme des règles de calcul pour la simulation des assemblages de dipôles ;

- comme les axiomes constitutifs du modèle des montages série-parallèle ;

- comme fonction(s) opérant sur des structures de données de types respectifs Resistor… ParallelMount et qui mettent en jeu le polymorphisme (plusieurs règles pour l'unique fonction Impedance), la récursivité (dans les cas de SeriesMount et ParallelMount), ainsi que les objets logiciels : le connecteur composite ^:= associe les règles aux types plutôt qu'à la fonction Impedance, ce qui correspond aux méthodes de la programmation orientée objets.

Il est remarquable que des expressions fonctionnelles représentent directement des imbrications de montages série ou parallèle. Cependant, une conception plus générale pour un réseau quelconque de dipôles repose sur une structure de graphe.

Dialogue interdisciplinaire

Grâce à son pouvoir unificateur, Mathematica facilite le dialogue entre disciplines, un dialogue dont le besoin se fait aujourd'hui particulièrement sentir.

Un langage fédérateur

- dialogue entre mathématiques et informatique, parce qu'à trois importants paradigmes de programmation (procédural qui est celui du langage C, fonctionnel qui est celui de langage Lisp, transformationnel ou par règles qui est celui de Snobol) on peut faire correspondre trois importantes théories de la calculabilité (machines de Turing, approche fonctionnelle de Church-Gödel, règles de récriture de Post-Markov).

- dialogue également entre mathématiques et physique dans la mesure où le passage des axiomes aux règles de calcul effectivement programmées se réduit plus ou moins à une question d'orientation des égalités ; il s'agit en fait de l'algorithme de Knuth-Bendix (ou ses variantes). Réciproquement, pour chaque domaine particulier de la physique, les règles de calcul (orientées) déterminent les formules (non orientées) d'une axiomatique égalitaire donnant prise à l'étude mathématique par la théorie des modèles (sémantique dénotationnelle).

- dialogue enfin entre physique et informatique qui tient à ce que, sous l'influence de l'informatique, l'activité de modélisation se voit enrichie par l'approche algorithmique qui incite à organiser les théories en pensant au développement de programmes (fonctions opérant sur des structures de données) ; si bien que l'on conçoit désormais la modélisation en terme de combinaison de primitives.

Une réalisation pédagogique : mini-projets de modélisation avec Mathematica

Un langage adapté à la formulation des problème scientifiques et qui en outre stimule le dialogue interdisciplinaire est un bon candidat comme support à des mini-projets d'élèves-ingénieurs sur le thème de la modélisation.

L'ambition initiale était d'utiliser Mathematica comme outil d'intégration, de s'appuyer sur sa polyvalence pour enseigner non seulement les différents paradigmes de programmation et le calcul formel mais aussi les techniques numériques, l'algorithmique et la modélisation-simulation ; avec l'espoir de réaliser une économie pédagogique en évitant l'accumulation d'outils spécialisés et surtout la multiplication des syntaxes. Les réticences de la communauté enseignante ont finalement dévié l'objectif initial vers des travaux personnels d'étudiants sous forme de mini-projets.

Ces mini-projets sont organisés en première année de l'ENSMM (Besançon), école d'ingénieurs du groupe des ENSI. Apparentés aux TPE (travaux personnels encadrés) de l'enseignement secondaire ou aux TIPE (travaux d'initiative personnelle encadrés) des classes préparatoires, ils ont vocation à placer les étudiants en situation pédagogique active sur un sujet comprenant un volet étude (maths - physique) avec recherche documentaire et un volet développement (informatique) avec travail sur machine, complétés par un compte-rendu (rapport écrit ou exposé oral) ; le travail se fait sur un semestre, en petits groupes (de 3 élèves en général), avec des réunions de travail et des rapports intermédiaires, comme en entreprise.

La formation à Mathematica est fournie pour une part de façon classique (travaux dirigés sur machine) et pour une part en autoformation (les élèves recevant un polycopié). Les étudiants trouvent leur documentation en bibliothèque, sur Internet ou en consultant des enseignants-chercheurs spécialistes du sujet. La liste des sujets, les documents afférents aux projets, ainsi que quelques projets sélectionnés sont publiés sur le web (http://macmaths.ens2m.fr/students).

La plupart des sujets sont mutidisciplinaires : il s'agit d'aborder un problème de mathématiques sous l'angle de l'algorithmique ou le plus souvent un problème de physique par ses aspects mathématiques puis algorithmiques, autrement dit sous l'angle de la modélisation. Parce qu'il facilite cette approche interdisciplinaire, Mathematica joue dans ces projets un rôle fédérateur essentiel. D'ailleurs, le suivi d'une trentaine de thèmes chaque semestre eût été impossible sans le support indéfectible de ce logiciel.

Planning des mini-projets (un semestre)

On ne sera pas étonné que les étudiants apprécient ce type de pédagogie, qui leur donne l'occasion d'un apprentissage en contexte et peut-être aussi d'une relation plus authentique avec les enseignants. En effet, ces mini-projets rendent les élèves acteurs dans des rôles d'autoformation, de recherche d'information, de prise d'initiative, de travail en équipe, de choix de conception, d'interaction avec différents protagonistes, finalement plus proches de leur futur métier que l'enseignement traditionnel.

Néanmoins, toute innovation présente des risques et exige un délai de mise au point. Ici, trois années ont été nécessaires pour en affiner l'organisation. Il y a malheureusement lieu de déplorer le manque d'implication du corps enseignant et la réticence de beaucoup de collègues à faire évoluer leurs méthodes, tant est enracinée la croyance en une pédagogie du « transvasement » et de l'accumulation des connaissances.

Pourtant des prolongements sont déjà envisagés, tels que des actions de pédagogie coopérative sous forme de collaborations inter-établissements, avec partage de ressources au niveau d'un réseau d'institutions : non seulement les documents servant de support à ces mini-projets, d'ores et déjà publiés sur le web, mais aussi du conseil scientifique par e-mail ou par liste de discussion (tuteurs « virtuels »).

Quelques extraits

Nous présentons ici quelques extraits de projets, légèrement adaptés pour les besoins de la démonstration. Les mini-projets d'étudiants conduisent rarement à des produits finis et fiables, l'horaire disponible (une vingtaine d'heures dans notre cas) ne permettant pas d'atteindre une qualité professionnelle ; de sorte qu'il peut y subsister des imperfections et quelques erreurs. Les rapports originaux se trouvent à l'URL :  http://macmaths.ensmm.fr/students

Pour activer le programme de chaque exemple, il suffit d'évaluer le paragraphe intitulé "Programme".

Approche algorithmique des variétés et GAO

Dans les logiciels de conception assistée, la géométrie constitue souvent une interface aux programmes. Dans ce contexte algorithmique, définir une variété revient à établir une structure de données donnant la représentation paramétrique du domaine. Le modèle d'expression est Mapping[parametric, domain] où Mapping est un type, parametric une liste d'équations paramétriques et domain une séquence de listes imitant la syntaxe des domaines dans ParametricPlot ou Integrate. La représentation graphique des variétés peut être en partie sous-traitée aux commandes graphiques sauf dans les cas de domaines 3D ou de dimensions plus élevées, lesquels requièrent des commandes specifiques.

Programme (extrait)

\(\(\(ClearAll["Global`*"]\)\(
\)
    \)\)
\(\(\(Draw[
        Mapping[expr : {_, _, _}, du : {u_, umin_, umax_}, 
          dv : {v_, vmin_, vmax_}, dw : {w_, wmin_, wmax_}], \ opt___] ^:= 

      Show[
ParametricPlot3D[
          Evaluate[{expr /. u -> umin, expr /. u -> umax}], dv, dw, \ 
          DisplayFunction -> Identity, opt], 

        ParametricPlot3D[Evaluate[{expr /. v -> vmin, expr /. v -> vmax}], 
          du, dw, \ DisplayFunction -> Identity, opt], 

        ParametricPlot3D[Evaluate[{expr /. w -> wmin, expr /. w -> wmax}], 
          du, dv, \ DisplayFunction -> Identity, opt], \ 
        DisplayFunction -> $DisplayFunction, 
        opt
]\)\(
\)
    \)\)
Off[General::"spell1"];
Off[General::"spell"];

    
\(\(\(Transform[Mapping[{s__}, domain___], tr_] := 
	
      Mapping[Through[tr[s]], domain]\)\(
\)
    \)\)
Translate[m_, v_] := 
      Transform[m, 
        Thread[Function[
            Evaluate[{#1, #2, #3} + v]]]]

    
Move[m_, p_, v_] := 
      Transform[m, 
        Thread[Function[
            Evaluate[p . {#1, #2, #3} + v]]]]

    
On[General::"spell1"];
On[General::"spell"];

    
Volume[
        Mapping[p : {_, _, _}, du : {u_, _, _}, dv : {v_, _, _}, 
          dw : {w_, _, _}]] ^:= 
Integrate[
        Simplify[Det[Outer[D, p, {u, v, w}]]], du, dv, 
        dw]
  

Cylinder[r_, h_] := 
      Mapping[{ρ Cos[θ], ρ Sin[θ], z}, {ρ, 0, 
          r}, {θ, 0, 2  π}, {z, -h/2, h/2}]

Démonstration

On peut définir un domaine avec des paramètres numériques ou symboliques. En revanche, les représentations graphiques supposent des données numériques.

m = 
        Mapping[{r Cos[θ], r Sin[θ], z}, {r, r1, 
            r2}, {θ, 0, 3  π/2}, {z, 0, h}];

Draw[m /. {r1 -> 1/2, r2 -> 1, h -> 1}];

Toutes sortes de calculs numériques ou symboliques sont possibles, tels que volume (algébrique), centre d'inertie, tenseur d'inertie… Ici nous calculons le volume d'un secteur de couronne.

Volume[m]

On peut définir des variétés standard (d'usage courant) et aussi des transformations géometriques. Voici un cylindre à l'origine (pour afficher ces graphiques, il suffit d'activer le programme puis d'évaluer les entrées),

Draw[Cylinder[1, 2], 
      PlotRange -> {{-3, 3}, {-3, 3}, {-3, 3}}]

…puis après un déplacement,

Draw[
      Move[Cylinder[1, 
          2], {{Cos[Pi/4], 0, -Sin[Pi/4]}, {0, 1, 0}, {Sin[Pi/4], 0, 
            Cos[Pi/4]}}, {-1, 0, 1}], 
      PlotRange -> {{-3, 3}, {-3, 3}, {-3, 3}}]

…ou encore déformé par une transformation, passée comme fonction anonyme.

Draw[Transform[Cylinder[1, 1], {#1 - #3/2 &, #2 - #3/2 &, #3 &}], 
      PlotRange -> All, Axes -> None, 
      BoxStyle -> GrayLevel[0.5]]

Plusieurs groupes ont travaillé sur cette approche algorithmique des variétés ou l'ont réutilisée pour des applications en mécanique ou en DAO.

Spectroscopie ionique (calcul de trajectoires)

En vue d'applications en spectroscopie ionique, ce programme établit et résout les équations différentielles du mouvement pour des particules chargées assorties de conditions initiales et soumises à la combinaison d'un champ électrique et d'un champ magnétique. La plupart des paramètres sont passés sous forme d'options.

Programme (extrait)

ClearAll["Global`*"]

Options[LorentzTrajectory] = {Mass -> 1, Charge -> 1, 
        InitialPosition -> {0, 0, 0}, InitialVelocity -> {0, 0, 0}, 
        ElectricField -> {0, 0, 0}, 
        MagneticField -> {0, 0, 
            0}}; 

\(LorentzTrajectory[x_, t_, theOptions___] := 
	
      ReleaseHold[\(Hold[
              Flatten[DSolve[
                  Flatten[{
		Thread[
                        Mass\ D[x, {t, 2}] == 
                          Charge\ \((ElectricField + 
                                D[x, t]\[Cross]
                                  MagneticField)\)], 
		Thread[\((x /. 
                              t -> 0)\) == 
                          InitialPosition], 
		Thread[\((D[x, t] /. 
                              t -> 0)\) == InitialVelocity]}
	], x, 
                  t]]] /. {theOptions}\) /. 
          Options[LorentzTrajectory]]\)

Démonstration

On définit l'inconnue (vectorielle) du problème.

X[t_] = Through[{x, y, z}[t]]

Le mouvement par défaut est le repos à l'origine. Ensuite, on obtient le mouvement d'inertie lorsque la force est nulle.

LorentzTrajectory[X[t], t]

LorentzTrajectory[Through[{x, y, z}[t]], t, 
      InitialPosition -> {x0, y0, z0}, 
      InitialVelocity -> {u0, v0, w0}]

Voici une configuration classique de spectroscope ionique, avec une vitesse initiale et seulement un champ magnétique. La trajectoire bien connue est un arc de cercle.

FullSimplify[
      LorentzTrajectory[Through[{x, y, z}[t]], t, 
        InitialVelocity -> {0, v0, 0}, 
        MagneticField -> {0, 0, b}]]

Enfin, voici une autre configuration.

trajectory = 
      FullSimplify[
        LorentzTrajectory[X[t], t, InitialVelocity -> {v0, 0, 0}, 
          ElectricField -> {0, e, 0}, 
          MagneticField -> {0, b, 0}, 
Charge -> q,  
          Mass -> m]]

On peut alors introduire des valeurs numériques, directement ou à l'aide de l'extension PhysicalConstants`.

Needs["Miscellaneous`PhysicalConstants`"]

numericalValues = {q -> First[ElectronCharge], 
          m -> First[ProtonMass], v0 -> 10. ^6, b -> 1. , 
          e -> 10. ^4};

ParametricPlot3D[
        Evaluate[X[t] /. Flatten[trajectory] /. numericalValues], {t, 0, 
          10 Pi m/q /. numericalValues}, 
        PlotPoints -> 150];

Probablement un meilleur programme serait-il scindé en calcul du système différentiel d'un côté et sa résolution de l'autre, avec DSolve, NDsolve ou au moyen de méthodes approchées (séries, perturbations…).

Modélisation en électronique (ou optique)

La modélisation en électronique fournit un exemple où les programmes peuvent être organisés en modules, ou couches logicielles. Ici, on part d'un programme de calcul d'impédances de dipôles (déjà présenté plus haut) et on l'étend au calcul de matrices de tranfert de quadripôles.

Programme (extrait)

ClearAll["Global`*"]

    
\(\(\(Needs["Graphics`Graphics`"]\)\(
\)\(
\)\( (*\ Impedance\ *) \)\(
\)
    \)\)
Impedance[Inductor[l_], w_:  ω] ^:= I l w
Impedance[Capacitor[c_], w_:  ω] ^:= -I/c/w
Impedance[Resistor[r_], w_:  ω] ^:= 
      r

    
\(\(\(Impedance[SeriesMount[s_], w_:  ω] ^:= 
      Simplify[Apply[Plus, Thread[Impedance[s, w]]]]\)\(
\)
    \)\)
\(Impedance[ParallelMount[s_], w_:  ω] ^:= 
      Simplify[1/
          Apply[Plus, 
            1/Thread[
                Impedance[s, 
                  w]]]]


 (*\ Transfer\ *) 
\)
TransferMatrix[SerialMount[c_], 
        w_:  ω] := {{1, -Impedance[c, w]}, {0, 
          1}}

TransferMatrix[ShuntMount[c_], 
        w_:  ω] := {{1, 0}, {-1/Impedance[c, w], 
          1}}

\(TransferMatrix[CascadeMount[s_], w_:  ω] := 
      Apply[Dot, Thread[TransferMatrix[Reverse[s], w]]]
\)
\(TransferMatrix[PowerMount[m_, n_], w_:  ω] := 
      MatrixPower[TransferMatrix[m, w], n]
\)
ToTransferFunction[m_] := 
      Det[m]/m[[2, 
            2]]


 (* Common mounts *) 

\(GammaMount[c1_, c2_] := 
      CascadeMount[{ShuntMount[c1], 
          SerialMount[c2]}]
\)
\(TeeMount[c1_, c2_, c3_] := 
      CascadeMount[{SerialMount[c1], ShuntMount[c2], 
          SerialMount[c3]}]
\)
\(PiMount[c1_, c2_, c3_] := 
      CascadeMount[{ShuntMount[c1], SerialMount[c2], 
          ShuntMount[c3]}]

 (*\ 
      Graphic\ commands\ *) 
\)
\(GainPlot[tr_, domain_, theOptions___] := 
      LogLinearPlot[20*Log[10, Abs[tr]], domain, 
        theOptions]
\)
\(\(PhasePlot[tr_, domain_, theOptions___] := 
        LogLinearPlot[Arg[tr], domain, 
          theOptions];\)
\)
\(BodePlot[tr_, domain_, opt___] := 
      Show[GraphicsArray[{{GainPlot[tr, domain, 
                DisplayFunction -> Identity, opt]}, {PhasePlot[tr, 
                domain, DisplayFunction -> Identity, opt]}}], 
        DisplayFunction -> $DisplayFunction]
\)
\(NyquistPlot[tr_, {w_, wMin_, wMax_}, theOptions___] := 
      Module[{g}, 
        ParametricPlot[
          Evaluate[{Re[tr], Im[tr]} /. w -> 10^g], {g, Log[10, wMin], 
            Log[10, wMax]}, theOptions]]
\)
SimpleNyquistPlot[tr_, domain_, theOptions___] := 
      ParametricPlot[{Re[tr], Im[tr]}, domain, theOptions]

Démonstration

Nous nous appuyons sur le fait que les montages quadripolaires peuvent se décomposer en les montages élémentaires dits série et parallèle (shunt). En fait, nous nous restreindrons ici aux montages en cascade.

Montages élémentaires de quadripôles :
montage série (serial) et parallèle (shunt)

Nous définissons un quadripôle simple (filtre passe-bas du premier ordre) avec des paramètres symboliques.

setup = 
        CascadeMount[{SerialMount[Resistor[r]], 
            ShuntMount[Capacitor[c]]}];

Nous calculons sa matrice de transfert, sa fonction de transfert puis traçons sa courbe de Nyquist en donnant des valeurs numériques à r et c.

tm = TransferMatrix[setup, ω];
MatrixForm[tm]

tf = ToTransferFunction[tm]

NyquistPlot[
        Evaluate[tf /. {r -> 10^3, c -> 10^-6}], {ω, 1, 
          10^6}];

On peut définir et réutiliser des montages usuels (gamma, té, pi…)

TransferMatrix[CascadeMount[{SerialMount[c1], GammaMount[c2, c3]}]] == 
      TransferMatrix[TeeMount[c1, c2, c3]]

Un autre exemple

Maintenant, calculons la fonction de transfert d'un filtre passe-bas du second ordre.

t[ω_] = 
      Chop[ToTransferFunction[
          TransferMatrix[
            CascadeMount[{SerialMount[Resistor[5.  10^2]], 
                SerialMount[
                  Inductor[
                    2.  10^(-2)]], 
ShuntMount[
                  Capacitor[
                    1.  10^(-9)]]}], ω]], 
10^(-15)]

Nous en traçons les lieux de Bode, avec l'amplitude en décibels et l'argument (ou phase) en dessous, avec une échelle logarithmique pour les pulsations. A la suite, nous traçons la courbe de Nyquist.

BodePlot[t[ω], {ω, 0, 10^7}, 
        AxesLabel -> {"MHz", None}, 
        Ticks -> {{{10^3, 0.001}, {10^6, 1}}, Automatic}];

NyquistPlot[t[ω], {ω, 1, 10^7}, 
        PlotRange -> {{-5, 5}, {-10, 0}}, 
        PlotPoints -> 40];

On peut utiliser la même représentation pour construire des modèles d'amplificateurs opérationnels, de filtres, d'oscillateurs, d'asservissements et on peut même les adapter à l'optique matricielle. Plusieurs groupes ont travaillé sur ce sujet plus ou moins en parallèle, de sorte qu'il fallait prendre garde à maintenir la cohérence d'ensemble.

Analyse de stabilité

Pour l'analyse de la stabilité de systèmes décrits par leur fonction de transfert, on abandonne ici les critères classiques de Routh ou Nyquist au profit du calcul formel des pôles suivi du test de signe de leurs parties réelles.

Programme (extrait)

ClearAll["Global`*"]

stable[tr_, s_] := 
      Apply[And, 
        Map[(# < 0) &, 
          Map[ComplexExpand, 
            Map[Re, s /. 
                Solve[Denominator[Together[tr]] == 0, s]]]]]

Démonstration

Nous testons la stabilité de quelques fonctions de transfert.

Map[
      stable[#, s] &, {((s - 1)/((s + 1) (s + 2))), 
        (s/((s + 1) (s - 1))), ((s - 1)/((s + 1) (s - a)))}]

Lorsque les paramètres sont numériques, le programme indique la stabilité par une valeur booléenne ; sinon, il fournit une condition de stabilité.

Visualisation de molécules

La visualisation de molécules est un sujet à la frontière de la chimie, de la géométrie et de la mécanique. La conception du programme est fondée sur la méthode VSEPR (Valence Shell Electron Pair Repulsion), méthode approchée couramment utilisée dans ce contexte. Les molécules sont décomposées en blocs génériques, chaque bloc correspondant à un atome central lié à des atomes périphériques par des liaisons à des angles spécifiques. Ces données sont placées dans différentes structures et le programme réalise l'assemblage des blocs.

Programme (extrait)

\(\(\(ClearAll["Global`*"]\)\(
\)\(
\)\( (*\ 
      Common\ tools\ *) \)\(
\)
    \)\)
a = 1. ;
p1 = {-1, 0, 0}; pm1 = {0, 1, 0};
p0 = {1, 0, 0}; 
    L0 = {p0, pm1, 
        p1};

  
matrix[
        t_] := {{1, 0, 0}, {0, Cos[t], -Sin[t]}, {0, Sin[t], 
          Cos[t]}}

    
magnitude[u_] := Sqrt[Apply[Plus, u^2]]
unitary[u_] := u/magnitude[u]

    
basis[p0_, pm_, 
        p1_] := 
With[{v = 1/2 (p1 - p0), 
          w = 1/2 (p1 + p0)}, {
unitary[
            v], 
unitary[pm - w], 
Cross[
            unitary[v], 
            unitary[pm - w]]
}]

    
new[l1_, 
        l3_] := {l1, (l1 + l3)/2, (l1 + l3)/
          2}

    
vector0[θ_] := {-1 - 2 Cos[θ], 2 Sin[θ], 
        0}
vector1[α_, β_] := {-1 - Cos[α] + Cos[β], 
        Sin[α] + Sin[β], 0}
\(\(\(vector2[α_, β_] := {\(-1\) - Cos[α] - 
          Cos[β], Sin[α] - Sin[β], 
        0}\)\(
\)\(
\)\(
\)\( (*\ Bonds\ *) \)\(
\)
    \)\)
\(\(\(L180[{l1_, l2_, l3_}] := 
      new[l1, l3] + {{0, 0, 0}, {\(-2\) a, a, 0}, {\(-3\) a, 0, 0}} . 
          Transpose[Inverse[basis[l1, l2, l3]]]\)\(
\)
    \)\)
\(\(\(L109[{l1_, l2_, l3_}] := 
      new[l1, l3] + 
        a*{{0, 0, 0}, 
              vector1[\((180 - 109.5)\) °, \((109.5 - 
                      90)\) °], 
              vector0[\((180 - 109.5)\)\ °]} . 
            Transpose[Inverse[basis[l1, l2, l3]]]\)\(
\)
    \)\)
\(\(\(L109Inv[{l1_, l2_, l3_}] := 
      new[l1, l3] + 
        a*{{0, 0, 0}, 
              vector2[\((180 - 109.5)\) °, \((109.5 - 
                      90)\) °], 
              vector0[\((180 - 109.5)\)\ °]} . 
            Transpose[Inverse[basis[l1, l2, l3]]]\)\(
\)
    \)\)
\(\(\(L109a120[{l1_, l2_, l3_}] := 
      new[l1, l3] + 
        a*{{0, 0, 0}, 
              vector1[\((180 - 109.5)\) °, \((109.5 - 
                      90)\) °], 
              vector0[\((180 - 109.5)\)\ °]} . 
            Transpose[
              Inverse[basis[l1, l2, l3]] . matrix[120  °]]\)\(
\)
    \)\)
\(\(\(L109a240[{l1_, l2_, l3_}] := 
      new[l1, l3] + 
        a*{{0, 0, 0}, 
              vector1[\((180 - 109.5)\) °, \((109.5 - 
                      90)\) °], 
              vector0[\((180 - 109.5)\)\ °]} . 
            Transpose[
              Inverse[basis[l1, l2, l3]] . matrix[240  °]]\)\(
\)
    \)\)
L120[{l1_, l2_, l3_}] := 
      new[l1, l3] + 
        a*{{0, 0, 0}, vector1[60.0  °, 30.0  °], 
              vector0[60.0 °]} . 
            Transpose[Inverse[basis[l1, l2, l3]]]

    
L120a180[{l1_, l2_, l3_}] := 
      new[l1, l3] + 
        a*{{0, 0, 0}, vector1[60.0  °, 30.0  °], 
              vector0[60.0 °]} . 
            Transpose[
              Inverse[basis[l1, l2, l3]] . 
                matrix[180  °]]


 (* 
      Block structures *) 

    
SetAttributes[AX2, HoldAll]
AX2[L1_, L2_] := {L1 = Reverse[L1], 
        L2 = L180[L1]}

    
SetAttributes[AX2E1, HoldAll]
\(\(\(AX2E1[L1_, L2_] := {L1 = Reverse[L1], L2 = L120[L1]}\)\(
\)
    \)\)
SetAttributes[AX2E2, HoldAll]
AX2E2[L1_, L2_] := {L1 = Reverse[L1], 
        L2 = L109[L1]}

    
SetAttributes[AX3, HoldAll]
\(\(\(AX3[L1_, L2_, L3_] := {L1 = Reverse[L1], L2 = L120[L1], 
        L3 = L120a180[L1]}\)\(
\)
    \)\)
SetAttributes[AX3E1, HoldAll]
AX3E1[L1_, L2_, L3_] := {L1 = Reverse[L1], L2 = L109[L1], 
        L3 = L109a120[L1]}

    
SetAttributes[AX4, HoldAll]
\(\(\(AX4[L1_, L2_, L3_, L4_] := {L1 = Reverse[L1], L2 = L109[L1], 
        L3 = L109a120[L1], L4 = L109a240[L1]}\)\(
\)
    \)\)
SetAttributes[AX4Inv, HoldAll]
\(\(\(AX4Inv[L1_, L2_, L3_, L4_] := {L1 = Reverse[L1], L2 = L109Inv[L1], 
        L3 = L109a120[L1], 
        L4 = L109a240[
            L1]}\)\(
\)\(
\)\(
\)\( (*\ 
      Display\ *) \)\(
\)
    \)\)
\(\(\(DrawBond[{l1_, l2_, l3_}] := {PointSize[0.05], Point[l1], 
          PointSize[0.025], Point[l3], Line[{l1, l3}]};\)\(
\)
    \)\)
\(\(\(Draw[Molecule[s_], opt___] := 
      Show[Graphics3D[Map[DrawBond, s, {2}]], opt, 
        PlotRange -> 
          All]\)\(
\)\(
\)\(
\)\( (*\ 
      A\ few\ molecules\ *) \)\(
\)
    \)\)
Octane = 
        Molecule[{AX4Inv[L0, Lb, Lc, Ld], AX4Inv[Lb, Le, Lf, Lg], 
            AX4Inv[Le, Lh, Li, Lj], AX4Inv[Lh, Lk, Ll, Lm], 
            AX4Inv[Lk, Ln, Lo, Lp], AX4Inv[Ln, Lq, Lr, Ls], 
            AX4Inv[Lq, Lt, Lu, Lv], 
            AX4Inv[Lt, Lw, Lx, Ly]}];

\(\(Styren\  (*\ monomere\ du\ polystyrene\ *)  = 
        Molecule[{AX3[L0, L1, L2], AX3[L2, L3, L4], AX3[L4, L5, L6], 
            AX3[L5, L7, L8], AX3[L7, L9, L10], AX3[L9, L11, L12], 
            AX3[L12, L13, L14], AX3[L14, L15, L16]}];\)
\)
VinylAcetate = 
        Molecule[{AX3[L0, L1, L2], AX3[L2, L3, L4], AX2[L4, L5], 
            AX3[L5, L6, L7], AX4[L7, L8, L9, L10]}];

Démonstration

Quelques définitions de molécules sont incluses dans le programme (pour afficher les graphiques, il suffit d'activer le programme puis d'évaluer les entrées).

Draw[Styren]

Draw[Octane, ViewPoint -> {0.7, -2.1, 2.5}];

Draw[VinylAcetate]

En fait, ce programme demande à être amélioré, à cause de variables globales dont il vaudrait mieux s'abstenir. En outre, il faudrait paramétrer les distances interatomiques, les tailles d'atomes et éventuellement introduire une coloration conventionnelle des atomes, ce que l'on peut obtenir par couplage avec une base de données. Enfin, les rotations autour des liaisons sont, dans cette version, fixées arbitrairement.

Autres sujets

D'autres sujets concernent par exemple le λ-calcul, le système RSA, les décimales de π, la transformation en Z, le codage de Huffman, la méthode de Newton, la méthode de Galerkin, les éléments finis, les réseaux électriques, les amplificateurs opérationnels, les oscillateurs, les vibrations mécaniques, la diffraction et les interférences, la diffusion thermique, les calculs de pH, les modèles compartimentaux… On trouvera la liste actualisée des sujets et une sélection de rapports à l'URL :  http://macmaths.ensmm.fr/students

Quelques perspectives en recherche et dans le domaine de l'ingénierie

Du versant théorique au versant pratique des applications de Mathematica, nous indiquons ici trois pistes d'investigations. Dans chaque cas, Mathematica offre des perspectives sur des usages que les langages classiques ne permettent même pas d'imaginer.

Correspondance de Curry-Howard

Utilisé dans le contexte des preuves de programmes, l'isomorphisme (ou plus prudemment correspondance) de Curry-Howard établit une relation entre la logique (ou du moins un sous-ensemble constructif) et l'algorithmique ; cette correspondance signifie que construire un programme ou sa preuve reviennent au même. On peut s'attendre à ce que les recherches de plus en plus actives en ce domaine conduisent à un rapprochement et peut-être une meilleure intégration des mathématiques et de l'informatique.

Ainsi, la correspondance associe les définitions itératives ou récursives aux preuves par récurrence. Prenons l’exemple de la factorielle ; avec les quantifications sous-entendues, on peut écrire :

\(\(fact[0] = 1 , fact[n - 1] = \(\(\((n - 1)\)!\) => fact[n] = \ \(n\ \ fact[n - 1] = \ \(n!\)\)\)\)\/\(fact[n] = \(n!\)\)\)

On prouve l’implication en posant fact[n]=n fact[n-1] ; le programme de la factorielle fact[0]=1 ; fact[n_]:= n fact[n-1] réside dans la preuve, ce que d'aucuns traduisent par le dicton : « Programmer, c'est prouver ». Accessoirement, on reconnaît dans la preuve le variant et l'invariant (de boucle) des traditionnelles leçons d'informatique : le variant (ici n) est le paramètre dont la stricte décroissance lors de l'évaluation garantit que la définition explicite fact[0]=1 sera atteinte ; l'invariant est la propriété caractérisant l'objectif du programme (ici fact[n]=n!).

fact[0] = 1; 
fact[n_] := n fact[n - 1]

fact[5]

Cette correspondance se traduit par un dictionnaire mettant face à face des éléments de logique et de programmation, dont voici une esquisse.

({{logique, algorithmique}, {hypothèses (préconditions), données}, {implication (spécification), fonction}, {preuve, réalisation, programme, règle}, {conclusion (postcondition), résultat}, {modus ponens, application}, {déduction, \(évaluation\ \((réduction)\)\)}, {démonstration, suivi d’évaluation (Trace)}, {axiome, primitive ou donnée atomique}, {théorème, expression ou fonction}})

Il apparaît que la preuve d’un programme fait partie intégrante de son écriture ; de sorte qu'un programme correct n’est autre qu’une formule juste et qu'une erreur de programme est de même nature qu’une erreur mathématique … Ces réflexions laissent entrevoir une approche fondatrice unitaire pour la logique et le calcul.

Approximations symboliques

Le développement des techniques numériques et à certains égards du calcul formel nous a fait perdre de vue les méthodes classiques de calcul analytique approché. Pourtant, plusieurs techniques numériques fondamentales se justifient dans un cadre fonctionnel foncièrement symbolique ; c’est le cas des approximations successives (espaces métriques), de la méthode de Newton (espaces de Banach) ou encore du procédé de Galerkin (espaces de Hilbert) dont la méthode des éléments finis est un cas particulier ; c’est également le cas de la méthode de perturbation (espaces de Banach). De sorte qu'entre les solutions symboliques exactes et les solutions numériques approchées, il y a place pour des solutions symboliques approchées.

Testons par exemple la méthode des approximations successives sur une équation intégrale de Fredholm dont on sait par ailleurs déterminer la solution φ[x]=(3 x+1)/2 par la méthode des noyaux dégénérés.

φ[x]==x+(1/2) -(∫_(-1)^1)(y + x) φ[
                y] dy

operator[u_,x_]:= Module[{y}, Simplify[
	x+Integrate[(y+x)(u/.x->y),{y,-1,1}]/2] ]

NestList[operator[#,x]&, 1, 3]

Après avoir calculé les premiers itérés, on visualise la convergence des approximations successives.

Show[
 Plot[(3x+1)/2,{x,-1,1},DisplayFunction->Identity],
 Plot[Evaluate[
	NestList[operator[#,x]&,0,4]],{x,-1,1},
	PlotStyle->{Dashing[{0.02,0.02}]},
	DisplayFunction->Identity],
 DisplayFunction->$DisplayFunction];

Les méthodes fonctionnelles s’avèrent une approche unitaire pour l’étude et le traitement des équations fonctionnelles : non seulement elles fournissent des outils théoriques (désormais classiques) pour les démonstrations d’existence, unicité et convergence, mais surtout elles conduisent à des procédés d’approximation symbolique. On doit s’attendre à une renaissance prochaine des travaux trop vite oubliés des Poincaré, Volterra, Timoshenko … Et l’on peut anticiper la constitution d’une analyse fonctionnelle algorithmique, support de la modélisation comme le fut l’analyse pendant des siècles.

Approche algorithmique de la modélisation

La modélisation et la simulation s'appuyant désormais presqu'inévitablement sur l'outil informatique, on est amené à les aborder en termes de structures de données et des fonctions afférentes, celles-ci s'exprimant comme combinaisons de primitives, autrement dit en termes algorithmiques. Il en résulte une approche modulaire, à l'image des dispositifs techniques modélisés que l'on cherche de plus en plus couramment à concevoir de façon modulaire.

Reprenons l'exemple du calcul des quadripôles. Le programme aussi bien que le modèle mathématique constituent une extension du cas des impédances ; on peut parler de réutilisation de modèles comme de réutilisation de programmes ou encore de modélisation en couches comme on parle de couches logicielles. D'autre part, ils s'appuient sur une conception modulaire des quadripôles — montages en cascade — d'ailleurs généralisable à d'autres types de montages ; la structure des expressions et des fonctions associées en est le reflet immédiat. Autrement dit, se font écho la modularisation des sytèmes physiques, celle de leurs modèles mathématiques et celle des programmes destinés à les simuler.

Calcul d'impédances

ClearAll["Global`*"]

    
Impedance[Resistor[r_], w_:  ω] ^:= r
Impedance[Inductor[l_], w_:  ω] ^:= I l w
Impedance[Capacitor[c_], 
        w_:  ω] ^:= -I/(c w)

    
\(Impedance[SeriesMount[s_], w_:  ω] ^:= 
	
      Apply[Plus, Thread[Impedance[s, w]]]\)
\(Impedance[ParallelMount[s_], w_:  ω] ^:= 
	
      1/Apply[Plus, 1/Thread[Impedance[s, w]]]\)

Matrices de transfert

A l'image de la décomposition du système physique en blocs élémentaires, le programme récursif TransferMatrix ramène le calcul de tout montage en cascade au cas des blocs élémentaires SerialMount ou ShuntMount.

TransferMatrix[SerialMount[c_], 
        w_:  ω] ^:= 
{{1, -Impedance[c, w]}, {0, 
          1}}
TransferMatrix[ShuntMount[c_], 
        w_:  ω] ^:= {{1, 0}, {-1/Impedance[c, w], 
          1}}

TransferMatrix[CascadeMount[s_], w_:  ω] ^:= 
      Apply[Dot, Thread[TransferMatrix[Reverse[s], w]]]

On a loisir de définir (nommer) des assemblages d'usage courant (gamma, té, pi…) et de les employer dans les calculs.

GammaMount[c1_, 
        c2_] := 
CascadeMount[{ShuntMount[c1], 
          SerialMount[c2]}]
TeeMount[c1_, c2_, 
        c3_] := 
CascadeMount[{SerialMount[c1], 
          ShuntMount[c2], SerialMount[c3]}]
PiMount[c1_, c2_, 
        c3_] := 
CascadeMount[{ShuntMount[c1], 
          SerialMount[c2], ShuntMount[c3]}]

setup = 
      CascadeMount[{SerialMount[Resistor[r]], 
GammaMount[
            Capacitor[c], Inductor[l]]}]; 
MatrixForm[TransferMatrix[setup, ω]]

Plus généralement, on peut réutiliser ces programmes, ou les modèles associés, en électronique (amplificateurs opérationnels, oscillateurs…), en automatique (asservissements) mais aussi en optique (optique matricielle). Les modèles comme les programmes sont génériques.

Il y a quelques années, on a beaucoup parlé des langages à objets en faisant miroiter la possibilité d'échanger des objets logiciels dédiés à la modélisation. Ces espoirs ont été largement déçus, entre autres parce que ces langages restent trop proches de la machine et que le calcul formel et la programmation symbolique leur font défaut. Avec sa syntaxe fonctionnelle, son évaluateur transformationnel et son approche des objets logiciels, Mathematica apporte une solution plus satisfaisante.

Conclusion : étudiants d'aujourd'hui, professionnels du futur

L'intitulé de l'exposé est "Intégration de Mathematica…" mais en fait c'est Mathematica qui constitue un outil d'intégration ; car grâce à sa syntaxe adaptée à l'expression des formules scientifiques, il facilite le dialogue interdisciplinaire et contribue en particulier à rapprocher des aspects scientifiques fondamentaux et des considérations pratiques en modélisation-simulation, via l'activité transversale qu'est la modélisation. A ce titre, il s'oppose à l'inquiétante déstructuration des connaisances actuellement observée.

Ces caractéristiques en font un excellent support pour une pédagogie par projets qui rapproche les étudiants de leur futur métier. A l'attitude plutôt réservée du corps enseignant, s'oppose la réaction encourageante des élèves, peut-être plus sensibles à ce qui touche leur avenir. Cet aspect est d'autant plus important que les étudiants formés aujourd'hui ne seront opérationnels que dans quelques années et n'atteindront leur maturité professionnelle que cinq à quinze ans plus tard ; il importe donc d'anticiper par des choix avant-gardistes judicieux.

Bibliographie

On trouvera une bibliographie plus étoffée dans la première référence.

R. Barrère, « Mathematica, calcul formel et programmation symbolique pour l'informatique scientifique », Vuibert, 2002 (voir aussi  http://macmaths.ensmm.fr/books)

R. Barrère, « Serveur d'informations pour les étudiants » [en ligne] http://macmaths.ensmm.fr/students

R. Erra, « Ateliers Mathematica », Vuibert, 2003

Y. Poitevineau, « Mathematica 3 par la pratique », Eyrolles, 1997

J. Zizi, « Mathematica pour classes préparatoires et DEUG scientifiques », Springer-Verlag, 1997

Remerciements

Je remercie les collègues qui ont participé à la mise au point de cette expérience pédagogique ainsi que les étudiants qui m'ont autorisé à rendre publics leurs rapports de projets ; ceux-ci se trouvent à l'URL : http://macmaths.ensmm.fr/students